package com.you.weixinpay.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.you.weixinpay.result.Result;
import com.you.weixinpay.service.WxPayService;
import com.you.weixinpay.utils.WeChatNativePayUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@CrossOrigin //跨域
@RestController
@RequestMapping("/api/wx-pay")
@Slf4j
@Tag(name = "微信支付")
public class WxPayController {
    @Resource
    private WxPayService wxPayService;
    @Resource
    private WeChatNativePayUtil weChatNativePayUtil;

    /**
     * Native下单
     *
     * @param productId 商品id
     * @return 返回支付二维码链接和订单号
     * @throws Exception 抛出各种异常
     */
    @Operation(summary = "Native下单")
    @PostMapping("/native/{productId}")
    public Result nativePay(@PathVariable Long productId) throws Exception {
        log.info("发起支付请求 v3");
        Map<String, Object> map = wxPayService.nativePay(productId);
        return Result.success().setData(map);
    }


    /**
     * 支付通知
     * @param request 请求
     * @param response 响应
     */
    @Operation(summary = "支付通知")
    @PostMapping("/native/notify")
    public String nativeNotify(HttpServletRequest request, HttpServletResponse response){
        log.info("支付通知开始");
        try {
            // 1. 获取请求体内容
            String body = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
            log.info("支付通知的完整数据：{}", body);
            log.info("支付通知的id===>{}",JSON.parseObject(body).get("id"));

            // 2.验证签名
            if (!weChatNativePayUtil.verifySignature(request, body)) {
                log.error("验证签名失败");
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 返回500
                return "验签失败";
            }

            // 3. 解析【支付】通知内容
            String eventType = WeChatNativePayUtil.parseEventType(body);
            if (!"TRANSACTION.SUCCESS".equals(eventType)) {
                log.warn("支付未成功，事件类型：{}", eventType);
                response.setStatus(HttpServletResponse.SC_OK); // 仍返回200成功响应，避免微信重复通
                return WeChatNativePayUtil.buildFailureResponse();
            }

            JSONObject resource = WeChatNativePayUtil.getResource(body);
            String decryptData = weChatNativePayUtil.processResource(resource);
            log.info("解密后的数据：{}", decryptData);

            //4.更新订单状态等业务操作
            JSONObject transaction = JSON.parseObject(decryptData);
            String outTradeNo = transaction.getString("out_trade_no"); // 商户订单号
            String transactionId = transaction.getString("transaction_id"); // 微信订单号
            wxPayService.processOrder(outTradeNo);
            //记录支付日志【可选，根据decryptData里解密的数据来写，这里就不写了】

            response.setStatus(HttpServletResponse.SC_OK); // 返回200
            return WeChatNativePayUtil.buildSuccessResponse();
        } catch (Exception e) {
            log.error("支付通知处理异常", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 返回500
            return "处理失败";
        }
    }

    /**
     * 申请退款
     * @param orderNo 订单号
     * @param reason 退款原因
     */
    @Operation(summary = "申请退款")
    @PostMapping("/refunds/{orderNo}/{reason}")
    public Result refund(@PathVariable String orderNo, @PathVariable String reason) throws Exception {
        log.info("申请退款");
        wxPayService.refund(orderNo, reason);
        return Result.success();
    }

    /**
     * 退款通知
     */
    @Operation(summary = "退款通知")
    @PostMapping("/refunds/notify")
    public String refundNotify(HttpServletRequest request, HttpServletResponse response) {
        log.info("退款通知开始");
        try {
            // 1. 获取请求体内容
            String body = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
            log.info("退款通知的完整数据：{}", body);
            log.info("退款通知的id===>{}",JSON.parseObject(body).get("id"));

            // 2.验证签名
            if (!weChatNativePayUtil.verifySignature(request, body)) {
                log.error("验证签名失败");
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);// 返回500
                return "验签失败";
            }

            // 3. 解析【退款】通知内容
            String eventType = WeChatNativePayUtil.parseEventType(body);
            if (!"REFUND.SUCCESS".equals(eventType)) {
                log.warn("退款未成功，事件类型：{}", eventType);
                response.setStatus(HttpServletResponse.SC_OK); // 仍返回200成功响应，避免微信重复通
                return WeChatNativePayUtil.buildFailureResponse();
            }

            JSONObject resource = WeChatNativePayUtil.getResource(body);
            String decryptData = weChatNativePayUtil.processResource(resource);
            log.info("解密后的退款数据：{}", decryptData);

            //4.更新退款状态等业务操作
            JSONObject refundData = JSON.parseObject(decryptData);
            String outRefundNo = refundData.getString("out_refund_no"); // 商户退款单号
            String refundStatus = refundData.getString("refund_status"); // 退款状态
            wxPayService.processRefund(outRefundNo, refundStatus);

            response.setStatus(HttpServletResponse.SC_OK); // 返回200
            return WeChatNativePayUtil.buildSuccessResponse();
        } catch (Exception e) {
            log.error("退款通知处理异常", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 返回500
            return "处理失败";
        }
    }

    /**
     * 用户取消订单
     * @param orderNo 订单号
     * @return 订单取消结果
     */
    @Operation(summary = "用户取消订单")
    @PostMapping("/cancel/{orderNo}")
    public Result cancel(@PathVariable String orderNo){
        log.info("取消订单");
        wxPayService.cancelOrder(orderNo);
        return Result.success().setMessage("订单已取消");
    }

    /**
     * 查询支付订单状态
     * @param orderNo  订单号
     * @return 订单查询结果
     */
    @Operation(summary = "查询支付订单状态【测试】")
    @GetMapping("/query/{orderNo}")
    public Result queryOrder(@PathVariable String orderNo) throws Exception{
        log.info("查询订单");
        String result = wxPayService.queryOrder(orderNo);
        return Result.success(result).setMessage("查询成功");
    }

    /**
     *查询退款状态
     * @param refundNo 退款单号
     */
    @Operation(summary ="查询退款状态【测试】")
    @GetMapping("/query-refund/{refundNo}")
    public Result queryRefund(@PathVariable String refundNo) throws Exception {
        log.info("查询退款");
        String result = wxPayService.queryRefund(refundNo);
        return Result.success(result).setMessage("查询成功");
    }

    /**
     * 查询交易账单
     * @param billDate 账单日期，格式yyyy-MM-dd
     * @param billType 账单类型：ALL-全部，SUCCESS-成功，REFUND-退款
     * @return 账单下载URL
     */
    @Operation(summary = "查询交易账单")
    @GetMapping("/querybill/{billDate}/{billType}")
    public Result queryTradeBill(
            @PathVariable String billDate,
            @PathVariable String billType) throws Exception {
        log.info("查询交易账单，日期：{}，类型：{}", billDate, billType);
        String downloadUrl = weChatNativePayUtil.queryTradeBill(billDate, billType);
        return Result.success(downloadUrl).setMessage("查询成功");
    }

    /**
     * 下载账单
     * @param downloadUrl 账单下载URL
     * @return 账单内容
     */
    @Operation(summary = "下载账单")
    @GetMapping("/download-bill")
    public Result downloadBill(@RequestParam String downloadUrl) throws Exception {
        log.info("下载账单，URL：{}", downloadUrl);
        String billContent = weChatNativePayUtil.downloadBill(downloadUrl);
        return Result.success(billContent).setMessage("下载成功");
    }
}
